<template>
  <SysDialog
    ref="dialogRef"
    @onSubmit="onSubmit"
    @onClose="onClose"
  >
    <template #content>
      <el-form
        ref="formRef"
        :model="form.data"
        style="max-width: 68%;margin: 0 auto;"
        label-width="auto"
      >
        <div v-for="(field, index) in filterdFields">
          <el-form-item
            :key="field.prop"
            :label="field.label + ':'"
            :prop="field.prop"
            :rules="field.formMeta?.rules"
            v-if="!(field.formMeta?.hideIf && field.formMeta.hideIf(form.data))"
          >
            <el-input
              v-if="field.formMeta?.type === 'text' || field.formMeta?.type === undefined"
              v-model="form.data[field.prop]"
              :placeholder="field.formMeta?.placeholder ? field.formMeta?.placeholder : field.label"
              :type="field.formMeta?.isPwd ? 'password' : 'text'"
              :show-password="field.formMeta?.isPwd"
              :disabled="field.formMeta?.disabledOn?.includes(form.mode)"
              clearable
            />
            <el-radio-group
              v-else-if="field.formMeta?.type === 'radio'"
              v-model="form.data[field.prop]"
              :disabled="field.formMeta?.disabledOn?.includes(form.mode)"
            >
              <el-radio
                v-for="opt in field.formMeta.options"
                :key="opt.value"
                :value="opt.value"
              >
                {{ opt.label }}
              </el-radio>
            </el-radio-group>
            <el-select
              v-else-if="field.formMeta?.type === 'select' || field.formMeta?.type === 'multi-select'"
              :multiple="field.formMeta?.type === 'multi-select' ? true : false"
              v-model="form.data[field.prop]"
              :placeholder="field.formMeta?.placeholder ? field.formMeta?.placeholder : '请选择' + field.label"
              clearable
              tag-effect="plain"
            >
              <el-option
                v-for="opt in field.formMeta.options"
                :key="opt.value"
                :value="opt.value"
                :label="opt.label"
              />
            </el-select>
            <el-tree-select
              v-else-if="field.formMeta?.type === 'tree-select'"
              v-model="form.data[field.prop]"
              :placeholder="field.formMeta?.placeholder ? field.formMeta?.placeholder : '请选择' + field.label"
              check-strictly
              :render-after-expand="false"
              show-checkbox
              check-on-click-node
              :default-expand-all="true"
              :data="field.formMeta?.options"
            >
            </el-tree-select>
          </el-form-item>
        </div>
      </el-form>
    </template>
  </SysDialog>
</template>

<script lang="ts" setup>

export type FormField = {
  label: string,
  prop: string,
  formMeta: FormFieldMeta
}

import type { Result } from '@/api/http/request'
import { FormMode } from '@/common/type/baseEnum'
import type { FormFieldMeta } from '@/common/type/field'
import SysDialog from '@/components/SysDialog.vue'
import { isResultSuccess } from '@/util/http'
import Logger from '@/util/log'
import { ElMessage } from 'element-plus'
import { nextTick, reactive, ref, watch } from 'vue'

const props = defineProps({
  formFields: {
    type: Array as () => FormField[],
    default: () => []
  },
  formHandlers: {
    type: Map<FormMode, (data: any) => Promise<Result<any>>>,
    // note!! default函数一定要写好!否则会各种报错
    default: () => new Map([[FormMode.Add, async (data: any) => { return { code: 0, msg: '添加成功' } }], [FormMode.Edit, async (data: any) => { return { code: 0, msg: '编辑成功' } }]])
  }
})

const filterdFields = ref<FormField[]>([])

const dialogRef = ref()
const formRef = ref()
const form = reactive(
  {
    data: {},
    mode: FormMode.Add
  }
)

const open = (m: FormMode, data: any) => {
  form.mode = m
  filterdFields.value = props.formFields.filter(
    field => !(field.formMeta?.hideInForm || field.formMeta?.hideOn?.includes(m)))
  // Logger.prettyInfo('open form fields', filterdFormFields.value)
  dialogRef.value.open(m)

  if (data) {
    // note: 这里的nextTick是为了保证表单数据填充的正确性
    nextTick(() => {
      Object.assign(form.data, data)
      // Logger.prettyInfo('open form data', data)
    })
  }
}

const onSubmit = () => {
  Logger.prettyInfo('submit start!', form.data)
  formRef.value.validate(async (valid: boolean, fields: any) => {
    if (valid) {
      let success = false, errMsg: any
      const f = props.formHandlers.get(form.mode)
      if (!f) {
        ElMessage.error('未找到有效处理函数！')
        return false
      }
      try {
        const res = await f(form.data)
        success = isResultSuccess(res)
        errMsg = res.msg
      } catch (error) {
        errMsg = error
        Logger.prettyError('operation catch error', error.response.data)
      }

      dialogRef.value.close()

      if (!success) {
        ElMessage.error('操作失败！' + errMsg)
        return false
      } else {
        ElMessage.success('操作成功！')
        emit('success')
        return true
      }
    } else {
      Logger.prettyError('error submit!!', fields)
      return false
    }
  })
}

const onClose = () => {
  formRef.value.resetFields()
  form.data = {}
}

defineExpose({
  open,
  form
})

const emit = defineEmits(['success'])

</script>